<script setup>
import { ElMessage } from 'element-plus'
import { computed, onMounted, watch } from 'vue'

const tableRef = ref(null)

const tableClass = computed(() => {
  return { 'el-table-scrollbar': props.scrollbar }
})

const props = defineProps({
  data: {
    required: true,
    type: Array,
    default: () => []
  },
  tableColumn: {
    required: true,
    type: Array,
    default: () => []
  },
  showStripe: {
    type: Boolean,
    default: true
  },
  showBorder: {
    type: Boolean,
    default: true
  },
  showSummary: {
    type: Boolean,
    default: false
  },
  scrollbar: {
    type: Boolean,
    default: true
  },
  pageSize: {
    type: Number,
    default: 20
  },
  total: {
    type: Number
  },
  remote: {
    type: Boolean,
    default: false
  },
  showPagination: {
    type: Boolean,
    default: true
  }
})

const emit = defineEmits([
  'selection-change',
  'row-dblclick',
  'filter-change',
  'sizeChange',
  'currentChange'
])

const tableData = ref(props.data)
const activeIndex = ref(0)
const tableColumn = ref([])

/**
 * @description: 新增行数据
 * @return {*}
 */
const addRow = row => {
  const { index } = row
  const props = tableColumn.value.map(item => item.prop)
  const rowData = props.reduce((curr, prev) => {
    curr[prev] = ''
    return Object.assign({}, curr)
  }, {})
  
  tableData.value.splice(index + 1, 0, { ...rowData, isEdit: false, index: index + 1 })
  resetTableSort()
}

/**
 * @description: 删除行数据
 * @param {*} row
 * @return {*}
 */
const deleteRow = row => {
  const { index } = row
  if (index === 0) {
    ElMessage.error('首行信息不可删除！')
    throw new Error('首行信息不可删除！')
  }
  tableData.value = tableData.value.splice(index, 1)
  resetTableSort()
}

// 初始化列信息
const defineColumn = () => {
  tableColumn.value = props.tableColumn.map(item => {
    item.type = item.type || 'text'
    return item
  })
}

// 初始化表格数据
const defineTableData = () => {
  const props = tableColumn.value.map(item => item.prop)
  const rowData = props.reduce((curr, prev) => {
    curr[prev] = ''
    return Object.assign({}, curr)
  }, {})
  tableData.value.push({ ...rowData, isEdit: false, index: 0 })
}

const onRowClick = row => {
  tableData.value.map(item => {
    item.isEdit = false
  })

  row.isEdit = true
}

const onCellMouseEnter = (row, cell, event) => {
  row.isEdit = true
}

const onCellMouseLeave = row => {
  if (row.index !== activeIndex.value) {
    row.isEdit = false
  }
}

const handleCurrentChange = currentRow => {
  activeIndex.value = currentRow.index
}

// 重置表格索引
const resetTableSort = () => {
  tableData.value.map((item, index) => {
    item.index = index
    return item
  })
}

onMounted(() => {
  defineColumn()
  defineTableData()
})
defineExpose({ $el: tableRef })
</script>

<template>
  <el-table
    ref="tableRef"
    v-bind="$attrs"
    :data="tableData"
    :stripe="$props.showStripe"
    :border="$props.showBorder"
    :show-summary="$props.showSummary"
    :scrollbar-always-on="$props.scrollbar"
    :class="tableClass"
    highlight-current-row
    @cell-mouse-enter="onCellMouseEnter"
    @cell-mouse-leave="onCellMouseLeave"
    @row-click="onRowClick"
    @current-change="handleCurrentChange"
    :header-cell-style="{ 'text-align': 'center' }"
  >
    <el-table-column label="" width="60" align="center">
      <template #default="scope">
        <el-row v-if="scope.row.isEdit">
          <el-col :span="12">
            <el-text type="primary" @click="addRow(scope.row)">
              <el-icon size="18"> <CirclePlusFilled /> </el-icon>
            </el-text>
          </el-col>
          <el-col :span="12">
            <el-text type="danger" @click="deleteRow(scope.row)">
              <el-icon size="18"> <CircleCloseFilled /> </el-icon>
            </el-text>
          </el-col>
        </el-row>

        <span v-else> {{ scope.row.index + 1 }} </span>
      </template>
    </el-table-column>

    <!-- 表身左侧的起始插槽，通常用于表单勾选 -->
    <template v-if="$slots.header">
      <slot name="header"></slot>
    </template>

    <el-table-column
      v-for="item in tableColumn"
      :key="item.prop"
      :align="item.align || 'center'"
      :width="item.width"
      :minWidth="item.minWidth"
      :prop="item.prop"
      :label="item.label"
      :filters="item.filters"
      :filter-multiple="item.filterMultiple"
      :column-key="item.columnKey"
      :fixed="item.fixed"
      show-overflow-tooltip
    >
      <!-- 当存在tooltip时，显示tooltip -->
      <template #header v-if="item.tooltip">
        <el-tooltip :content="item.tooltip" placement="top">
          <span>{{ item.label }}</span>
        </el-tooltip>
      </template>

      <template #default="scope">
        <template v-if="item.type === 'input'">
          <el-input v-if="scope.row.isEdit" v-model="scope.row.gddh">
            <template #suffix v-if="item.logKey">
              <el-icon @click="item.logEvent"><Tickets /></el-icon>
            </template>
          </el-input>
          <span v-else>{{ scope.row.gddh }}</span>
        </template>

        <span v-else="item.type === 'text'">{{ scope.row[item.prop] }}</span>
      </template>
    </el-table-column>

    <!-- 表身结尾插槽，通常是用于展示tag信息以及单行的操作 -->
    <template v-if="$slots.footer">
      <slot name="footer"></slot>
    </template>
  </el-table>
</template>

<style scoped lang="scss">
$scrollLineHeight: 0.8rem;

.el-table {
  &-scrollbar {
    :deep(.el-scrollbar) {
      overflow: unset;
    }

    :deep(.el-table__body-wrapper) {
      padding-bottom: $scrollLineHeight;
    }

    :deep(.el-scrollbar__bar) {
      bottom: -(($scrollLineHeight) - $scrollLineHeight * 0.2);
    }
  }
}
</style>
